package com.gitee.wsl.ext.number


import kotlin.math.roundToInt


fun ClosedRange<Float>.ticks(count: Int) = ticks(start,endInclusive,count)

@JvmName("ticksDouble")
fun ClosedRange<Double>.ticks(count: Int) = ticks(start,endInclusive,count)

/** See equivalent [d3 function](https://github.com/d3/d3-array#tick). */
fun ticks(start: Float, stop: Float, count: Int): List<Float> =
    ticks(start.toDouble(), stop.toDouble(), count).map { it.toFloat() }

/** See equivalent [d3 function](https://github.com/d3/d3-array#tick). */
 fun ticks(start: Double, stop: Double, count: Int): List<Double> {
    require(count > 0) { "Count must be positive, but was $count." }
    if (start == stop) return listOf(start)
    val reverse = stop < start
    val (min, max) = if (reverse) stop to start else start to stop
    val step = tickIncrement(min, max, count).toDouble()

    val ticks = if (step > 0) {
        var r0 = (min / step).roundToInt()
        if (r0 * step < start) r0 += 1
        var r1 = (max / step).roundToInt()
        if (r1 * step > stop) r1 -= 1

        val capacity = r1 - r0 + 1
        (0 until capacity).map { i -> (r0 + i) * step }
    } else {
        val negativeInverseStep = -step
        var r0 = (min * negativeInverseStep).roundToInt()
        if (r0 / negativeInverseStep < start) r0 += 1
        var r1 = (max * negativeInverseStep).roundToInt()
        if (r1 / negativeInverseStep > stop) r1 -= 1

        val capacity = r1 - r0 + 1
        (0 until capacity).map { i -> (r0 + i) / negativeInverseStep }
    }

    return if (reverse) ticks.asReversed() else ticks
}

